package com.tabnet.dao.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;

import com.tabnet.beans.gammeproduit.AppelOffre;
import com.tabnet.beans.personnes.Fournisseur;
import com.tabnet.dao.DAOAppelOffre;
import com.tabnet.dao.DAOException;
import com.tabnet.dao.DAOFactory;
import com.tabnet.dao.DAOUtilitaire;

public class AppelOffreDAOImpl implements DAOAppelOffre{
	
	private DAOFactory daoFactory;
	
	private static final String SQL_SELECT_ADMIN  		= "SELECT Ref_AO, Description_AO, DateEnvoie FROM AppelOffre ORDER BY DateEnvoie";
	private static final String SQL_SELECT_FOURNISSEUR	= "SELECT a.Ref_AO, Description_AO, DateEnvoie FROM AppelOffre a, Envoyer e, " +
														  "Fournisseur f WHERE a.Ref_AO = e.AO_Ref AND f.IDFournisseur = e.FournisseurID AND f.IDFournisseur = ? ORDER BY DateEnvoie";
	private static final String SQL_SELECT				= "SELECT IDFournisseur FROM Fournisseur";
	private static final String SQL_INSERT			 	= "INSERT INTO AppelOffre VALUES (?, ?, ?);";
	private static final String SQL_INSERT_ENVOYER	 	= "INSERT INTO Envoyer VALUES (?, ?);";
	private static final String SQL_APPEL_OFFRE			= "SELECT Ref_AO, Description_AO, date FROM AppelOffre WHERE Ref_AO = ?";
	private static final String SQL_MODIF				= "UPDATE AppelOffre SET Description_AO = ? WHERE Ref_AO = ?";
	private static final String SQL_SUPP_ADMIN			= "DELETE FROM AppelOffre WHERE Ref_AO = ?";
	private static final String SQL_SUPP_APPEL			= "DELETE FROM Envoyer WHERE AO_Ref = ?";
	private static final String SQL_SUPP_FOURNISSEUR	= "DELETE FROM Envoyer WHERE AO_Ref = ? AND FournisseurID = ?";
	
    public AppelOffreDAOImpl( DAOFactory daoFactory ) {
        this.daoFactory = daoFactory;
    }

	@Override
	public void addAppelOffre(AppelOffre appelOffre) throws DAOException {		
		Connection connexion = null;
        PreparedStatement preparedStatementA = null, preparedStatementF = null, preparedStatementE = null;
        ResultSet valeursAutoGenerees = null, rs = null;
        
        try {
            connexion = daoFactory.getConnection();
            
            //insertion de l'appel d'offre
	        preparedStatementA = DAOUtilitaire.initialisationRequetePreparee( connexion, SQL_INSERT, true,
	        		appelOffre.getRef(), appelOffre.getDescription(), appelOffre.get_date());
	        int statut = preparedStatementA.executeUpdate();
	        // récupération de la liste des identifiants des fournisseurs
	        preparedStatementF = DAOUtilitaire.initialisationRequetePreparee(connexion, SQL_SELECT, false);
	        rs = preparedStatementF.executeQuery();
	        
	        // enregistrement du lien entre chaque fournisseurs et l'appel d'offre ajouté
	        while(rs.next()){
	        	preparedStatementE = DAOUtilitaire.initialisationRequetePreparee(connexion, SQL_INSERT_ENVOYER, false,
	        			appelOffre.getRef(), rs.getString(1));
	        	preparedStatementE.executeUpdate();
	        }
	        
            if ( statut == 0) {
                throw new DAOException( "Échec de la création du de l'appel d'offre, aucune ligne ajoutée dans la table." );
            }
        } catch ( SQLException e ) {
            throw new DAOException( e );
        } finally {
        	 DAOUtilitaire.fermeturesSilencieuses( valeursAutoGenerees, preparedStatementF, connexion );
        }
	}

	@Override
	public void updAppelOffre(AppelOffre appelOffre) throws DAOException {
		Connection connexion = null;
        PreparedStatement preparedStatementF = null;
        ResultSet valeursAutoGenerees = null;

        try {
            connexion = daoFactory.getConnection();

            // modification de l'appel d'offre
		    preparedStatementF = DAOUtilitaire.initialisationRequetePreparee( connexion, SQL_MODIF, false,
		    		appelOffre.getDescription(), appelOffre.getRef() );
            
            int statut = preparedStatementF.executeUpdate();
            if ( statut == 0 ) {
                throw new DAOException( "Échec de la modification de l'appel d'offre, aucune ligne modifiée dans la table." );
            }
        } catch ( SQLException e ) {
            throw new DAOException( e );
        } finally {
        	 DAOUtilitaire.fermeturesSilencieuses( valeursAutoGenerees, preparedStatementF, connexion );
        }
	}

	@Override
	public AppelOffre trouverAppelOffre(String ref) throws DAOException {
		Connection connexion = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        AppelOffre appel = new AppelOffre();

        try {
            /* Récupération d'une connexion depuis la Factory */
            connexion = daoFactory.getConnection();
            /*
             * Préparation de la requête avec les objets passés en arguments
             * (ici, uniquement un id) et exécution.
             */
            preparedStatement =  DAOUtilitaire.initialisationRequetePreparee( connexion, SQL_APPEL_OFFRE, false, ref );
            resultSet = preparedStatement.executeQuery();
            /* Parcours de la ligne de données retournée dans le ResultSet */
            if ( resultSet.next() ) {
            	appel.setRef(resultSet.getString("Ref_AO"));
            	appel.setDescription(resultSet.getString("Description_AO"));
            	appel.set_date(resultSet.getDate("DateEnvoie"));
            }
        } catch ( SQLException e ) {
            throw new DAOException( e );
        } finally {
            DAOUtilitaire.fermeturesSilencieuses( resultSet, preparedStatement, connexion );
        }

        return appel;
	}

	@Override
	public void delAppelOffreFourn(AppelOffre appelOffre, Fournisseur fourn) throws DAOException {
		// supprime le lien avec le fournisseur
		Connection connexion = null;
        PreparedStatement preparedStatementF = null;
        ResultSet valeursAutoGenerees = null;

        try {
            connexion = daoFactory.getConnection();

            // modification de l'appel d'offre
		    preparedStatementF = DAOUtilitaire.initialisationRequetePreparee( connexion, SQL_SUPP_FOURNISSEUR, false,
		    		appelOffre.getRef(), fourn.get_IdF() );            
            int statut = preparedStatementF.executeUpdate();
            
            if ( statut == 0 ) {
                throw new DAOException( "Échec de la suppression de l'appel d'offre, aucune ligne modifiée dans la table." );
            }
        } catch ( SQLException e ) {
            throw new DAOException( e );
        } finally {
        	 DAOUtilitaire.fermeturesSilencieuses( valeursAutoGenerees, preparedStatementF, connexion );
        }
	}

	@Override
	public void delAppelOffreAdmin(AppelOffre appelOffre) throws DAOException {
		// supprime l'appel d'offre et le lien avec tous les fournisseurs
		Connection connexion = null;
        PreparedStatement preparedStatementF = null;
        ResultSet valeursAutoGenerees = null;

        try {
            connexion = daoFactory.getConnection();

            // modification de l'appel d'offre
		    preparedStatementF = DAOUtilitaire.initialisationRequetePreparee( connexion, SQL_SUPP_APPEL, false,
		    		appelOffre.getRef());            
            int statut = preparedStatementF.executeUpdate();
            
            preparedStatementF = DAOUtilitaire.initialisationRequetePreparee( connexion, SQL_SUPP_ADMIN, false,
            		appelOffre.getRef());            
    		preparedStatementF.executeUpdate();
            
            if ( statut == 0 ) {
                throw new DAOException( "Échec de la suppression de l'appel d'offre, aucune ligne modifiée dans la table." );
            }
        } catch ( SQLException e ) {
            throw new DAOException( e );
        } finally {
        	 DAOUtilitaire.fermeturesSilencieuses( valeursAutoGenerees, preparedStatementF, connexion );
        }
	}

	@Override
	public HashMap<String, AppelOffre> listerAppelFourn(Fournisseur fourn) throws DAOException {
		Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        HashMap<String, AppelOffre> lesAppels = new HashMap<String, AppelOffre>();
        AppelOffre appel;

        try {
            connection = daoFactory.getConnection();
            // récupération des fournissseurs
            preparedStatement = DAOUtilitaire.initialisationRequetePreparee( connection, 
            					SQL_SELECT_FOURNISSEUR, false, fourn.get_IdF() );
            resultSet = preparedStatement.executeQuery();
            while ( resultSet.next() ) {
            	appel = map( resultSet );
            	lesAppels.put(appel.getRef(), appel);
            }
        } catch ( SQLException e ) {
            throw new DAOException( e );
        } finally {
            DAOUtilitaire.fermeturesSilencieuses( resultSet, preparedStatement, connection );
        }

        return lesAppels;
	}

	@Override
	public HashMap<String, AppelOffre> listerAppelAdmin() throws DAOException {		
		Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        HashMap<String, AppelOffre> lesAppels = new HashMap<String, AppelOffre>();
        AppelOffre appel;

        try {
            connection = daoFactory.getConnection();
            // récupération des fournissseurs
            preparedStatement = DAOUtilitaire.initialisationRequetePreparee( connection, SQL_SELECT_ADMIN, false );
            resultSet = preparedStatement.executeQuery();
            while ( resultSet.next() ) {
            	appel = map( resultSet );
            	lesAppels.put(appel.getRef(), appel);
            }
        } catch ( SQLException e ) {
            throw new DAOException( e );
        } finally {
            DAOUtilitaire.fermeturesSilencieuses( resultSet, preparedStatement, connection );
        }

        return lesAppels;
	}
	
	/*
     * Simple méthode utilitaire permettant de faire la correspondance (le
     * mapping) entre une ligne issue de la table des fournisseurs (un ResultSet) et
     * un bean Fournisseur.
     */
    private static AppelOffre map( ResultSet resultSet ) throws SQLException {
    	AppelOffre appel = new AppelOffre();
    	
    	appel.setRef( resultSet.getString( "Ref_AO" ) );
    	appel.setDescription( resultSet.getString( "Description_AO" ) );
    	appel.set_date( resultSet.getDate( "DateEnvoie" ) );

        return appel;
    }

}
